package com.xiaoluo.service;

import com.squareup.okhttp.*;
import com.xiaoluo.common.enums.ServerTypeEnum;
import com.xiaoluo.common.k8s.KubernetesClientFactory;
import com.xiaoluo.common.ssl.XLTrustManager;
import com.xiaoluo.web.form.KubeServiceForm;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.dsl.Listable;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.net.Proxy;
import java.security.KeyManagementException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Project : XL-CD
 * Package : com.xiaoluo.service
 * Created by Willian.
 * Date  : 2016/1/29 17:46.
 */
@Service
public class KubernetesService {

    private final static String LABEL_TAG="app";
    private final static String LABEL_SERVICE="-svc";
    private final static String PRERELEASE_NAMESPACE="prerelease";
    private final static String DEFAULT_NAMESPACE="default";

    private String testUserName;
    private String testPassWord;
    private String testMasterUrl;

    private String userName;
    private String passWord;
    private String masterUrl;

    /**
     * k8s测试环境Client
     */
    private  DefaultKubernetesClient testClient;
    /**
     * k8s正式环境Client
     */
    private DefaultKubernetesClient client;

    /**
     * 获取k8s 测试环境client.
     * @return
     */
    public DefaultKubernetesClient getTestClient(){
        if(testClient == null){
            try {
                testClient = KubernetesClientFactory.newClient(testMasterUrl,testUserName,testPassWord);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return testClient;
    }

    /**
     * 获取k8s生产环境Client.
     * @return
     */
    public DefaultKubernetesClient getClient(){
        if(client == null){
            try {
                client = KubernetesClientFactory.newClient(masterUrl,userName,passWord);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return client;
    }

    /**
     * 查询服务运行状态
     *
     * 服务名称、端口
     * Pod状态
     * ReplicaController 实例数
     *
     * @param serviceName
     */
    public KubeServiceForm findService(String serviceName,ServerTypeEnum type){
        if(type != null && type.equals(ServerTypeEnum.TEST)){
            return getKubeServiceForm(getTestClient(),serviceName,type);
        }else {
            return getKubeServiceForm(getClient(),serviceName,type);
        }
    }

    /**
     *
     * @param type
     * @return
     */
    public List<KubeServiceForm> findServices(ServerTypeEnum type,String namespace){
        if(type != null && type.equals(ServerTypeEnum.TEST)){
            return getKubeServiceForms(getTestClient(),namespace);
        }else {
            return getKubeServiceForms(getClient(),namespace);
        }
    }

    private List<KubeServiceForm> getKubeServiceForms(DefaultKubernetesClient client,String namespace){
        List<KubeServiceForm> result = new ArrayList<KubeServiceForm>();

        ServiceList serviceList = client.inNamespace(namespace).services().list();
        if(serviceList != null && serviceList.getItems().size() >0){
            for(io.fabric8.kubernetes.api.model.Service service : serviceList.getItems()){
                KubeServiceForm temp = new KubeServiceForm();

                temp.setName(service.getMetadata().getName());
                temp.setNamespace(service.getMetadata().getNamespace());

                //service
                if(service.getSpec().getPorts() != null && service.getSpec().getPorts().size() >0){
                    List<ServicePort> ports = service.getSpec().getPorts();
                    temp.setPort(ports.get(0).getPort());
                    temp.setNodePort(ports.get(0).getNodePort());
                    if(ports.get(0).getTargetPort() != null)
                        temp.setTargetPort(ports.get(0).getTargetPort().getIntVal());

                    temp.setProtocol(ports.get(0).getProtocol());
                }

                if(service.getMetadata().getLabels() != null){
                    temp.setUuid(service.getMetadata().getLabels().get("uuid"));
                }

                //pod & replication
                if(service.getSpec().getSelector() != null){
                    temp.setSelector(service.getSpec().getSelector().toString());
                    for(String key : service.getSpec().getSelector().keySet()){
                        //replication
                        ReplicationControllerList replicationController = client.replicationControllers()
                                                                            .inNamespace(service.getMetadata().getNamespace())
                                                                                .withLabelIn(key, service.getSpec().getSelector().get(key)).list();
                        if(replicationController != null && replicationController.getItems().size() >0){
                            temp.setReplicas(replicationController.getItems().get(0).getSpec().getReplicas());
                        }

                        //pod
                        PodList list = client.pods()
                                                .inNamespace(service.getMetadata().getNamespace())
                                                    .withLabelIn(key, service.getSpec().getSelector().get(key)).list();

                        if(list != null && list.getItems() != null){
                            List<Pod> pods = list.getItems();
                            for(Pod pod :pods){
                                temp.setStatus(pod.getStatus().getPhase());
                                temp.setHostIp(pod.getStatus().getHostIP());
                                temp.setPodIp(pod.getStatus().getPodIP());
                                if(pod.getStatus().getContainerStatuses() != null && pod.getStatus().getContainerStatuses().size() >0){
                                    temp.setReady(pod.getStatus().getContainerStatuses().get(0).getReady().toString());
                                    temp.setMsg(pod.getStatus().getContainerStatuses().get(0).getState().toString());
                                    temp.setImages(pod.getStatus().getContainerStatuses().get(0).getImage());
                                }
                            }
                        }
                    }
                }

                temp.setClusterIp(service.getSpec().getClusterIP());
                //pod

                result.add(temp);
            }
        }
        Collections.sort(result);
        return result;
    }

    /**
     *
     * @param client
     * @param serviceName
     * @return
     */
    private io.fabric8.kubernetes.api.model.Service getService(DefaultKubernetesClient client,String serviceName,ServerTypeEnum type){
        ServiceList serviceList = null;
        if(type.equals(ServerTypeEnum.PREPRODUCT)){
            serviceList = client.inNamespace(PRERELEASE_NAMESPACE).services().list();
        }else{
            serviceList = client.inNamespace(DEFAULT_NAMESPACE).services().list();
        }


        if(serviceList != null && serviceList.getItems().size() >0) {
            for (io.fabric8.kubernetes.api.model.Service service : serviceList.getItems()) {
                if(service.getMetadata().getName().equals(serviceName)){
                    return  service;
                }
            }
        }
        return null;
    }
    /**
     * 获取进程相关信息
     * @param client
     * @param serviceName
     * @return
     */
    private KubeServiceForm getKubeServiceForm(DefaultKubernetesClient client,String serviceName,ServerTypeEnum type){
        KubeServiceForm result = new KubeServiceForm();



        io.fabric8.kubernetes.api.model.Service service = getService(client,serviceName,type);// client.services().inNamespace(DEFAULT_NAMESPACE).withName(serviceName).get();

        if(service != null){
            result.setName(service.getMetadata().getName());
            result.setNamespace(service.getMetadata().getNamespace());

            //service
            if(service.getSpec().getPorts() != null && service.getSpec().getPorts().size() >0){
                List<ServicePort> ports = service.getSpec().getPorts();
                result.setPort(ports.get(0).getPort());
                result.setNodePort(ports.get(0).getNodePort());
                if(ports.get(0).getTargetPort() != null)
                    result.setTargetPort(ports.get(0).getTargetPort().getIntVal());

                result.setProtocol(ports.get(0).getProtocol());
            }

            if(service.getMetadata().getLabels() != null){
                result.setUuid(service.getMetadata().getLabels().get("uuid"));
            }
            //replication
            ReplicationController replicationController = client.replicationControllers().inNamespace(service.getMetadata().getNamespace()).withName(serviceName).get();
            if(replicationController != null){
                result.setReplicas(replicationController.getSpec().getReplicas());
            }

            result.setSelector(service.getSpec().getSelector().toString());
            result.setClusterIp(service.getSpec().getClusterIP());
            //pod
            PodList list = client.pods().inNamespace(service.getMetadata().getNamespace()).withLabelIn(LABEL_TAG,serviceName).list();
            if(list != null && list.getItems() != null){
                List<Pod> pods = list.getItems();
                for(Pod pod :pods){
                    result.setStatus(pod.getStatus().getPhase());
                    result.setHostIp(pod.getStatus().getHostIP());
                    result.setPodIp(pod.getStatus().getPodIP());

                    if(pod.getStatus().getContainerStatuses() != null && pod.getStatus().getContainerStatuses().size() >0){
                        result.setReady(pod.getStatus().getContainerStatuses().get(0).getReady().toString());
                        result.setMsg(pod.getStatus().getContainerStatuses().get(0).getState().toString());
                        result.setImages(pod.getStatus().getContainerStatuses().get(0).getImage());
                    }
                }
            }
        }

        return result;
    }

    /**
     * 停止服务
     * @param serviceName
     * @param type
     */
    public void stopService(String serviceName,ServerTypeEnum type){
        if(type != null && type.equals(ServerTypeEnum.TEST)){
            stopService(getTestClient(), serviceName,type);
        }else {
            stopService(getClient(),serviceName,type);
        }
    }

    /**
     * 删除运行实例
     * @param client
     * @param serviceName
     */
    private void stopService(DefaultKubernetesClient client,String serviceName,ServerTypeEnum type){
        io.fabric8.kubernetes.api.model.Service service = getService(client,serviceName,type);
        if(service != null){
            client.services().inNamespace(service.getMetadata().getNamespace()).withName(serviceName).delete();
            client.replicationControllers().inNamespace(service.getMetadata().getNamespace()).withName(serviceName).delete();
        }
    }

    /**
     *
     * @param serviceName
     * @param instance
     * @param type
     */
    public void scale(String serviceName,Integer instance,ServerTypeEnum type){
        if(type != null && type.equals(ServerTypeEnum.TEST)){
            io.fabric8.kubernetes.api.model.Service service = getService(getTestClient(),serviceName,type);
            if(service != null)
                getTestClient().replicationControllers().inNamespace(service.getMetadata().getNamespace()).withName(serviceName).scale(instance);
        }else {
            io.fabric8.kubernetes.api.model.Service service = getService(getClient(),serviceName,type);
            if(service != null)
                getClient().replicationControllers().inNamespace(service.getMetadata().getNamespace()).withName(serviceName).scale(instance);
        }
    }

    public String getTestUserName() {
        return testUserName;
    }

    public void setTestUserName(String testUserName) {
        this.testUserName = testUserName;
    }

    public String getTestPassWord() {
        return testPassWord;
    }

    public void setTestPassWord(String testPassWord) {
        this.testPassWord = testPassWord;
    }

    public String getTestMasterUrl() {
        return testMasterUrl;
    }

    public void setTestMasterUrl(String testMasterUrl) {
        this.testMasterUrl = testMasterUrl;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public String getMasterUrl() {
        return masterUrl;
    }

    public void setMasterUrl(String masterUrl) {
        this.masterUrl = masterUrl;
    }
}
